
#include "rtthread.h"
#include "rthw.h"

/* 线程就绪列表 */
rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
/* 线程就绪优先级组 */
rt_uint32_t rt_thread_ready_priority_group;
/* 当前线程结构体指针	*/
struct rt_thread *rt_current_thread;
/* 当前优先级 */
rt_uint8_t rt_current_priority;

/**
 * @ingroup SystemInit
 * This function will initialize the system scheduler
 */
void rt_system_scheduler_init(void)
{
#if 0
    register rt_base_t offset;

    for (offset = 0; offset < RT_THREAD_PRIORITY_MAX; offset ++)
    {
        rt_list_init(&rt_thread_priority_table[offset]);
    }

    rt_current_priority = RT_THREAD_PRIORITY_MAX - 1;
    rt_current_thread = RT_NULL;
#else
    register rt_base_t offset;
		/* 线程优先级表初始化 */
    for (offset = 0; offset < RT_THREAD_PRIORITY_MAX; offset ++)
    {
        rt_list_init(&rt_thread_priority_table[offset]);
    }
		/* 初始化当前优先级为空闲线程的优先级 */
		rt_current_priority = RT_THREAD_PRIORITY_MAX - 1;
		/* 初始化当前线程控制块指针 */
		rt_current_thread = RT_NULL;
		/* 初始化线程就绪优先级组 */
		rt_thread_ready_priority_group = 0;
#endif	
}


/**
 * @ingroup SystemInit 第一次调度启动
 * This function will startup scheduler. It will select one thread
 * with the highest priority level, then switch to it.
 */
void rt_system_scheduler_start(void)
{
#if 0
    register struct rt_thread *to_thread;

    /* 手动指定第一个运行的线程 */
	  /* rt_thread_priority_table[0].next为tlist实例地址，((rt_thread *)0)->tlist 为tlist在rt_thread结构体中的偏移，tlist实例地址-偏移=rt_thread实例地址*/
    to_thread = rt_list_entry(rt_thread_priority_table[0].next,
                              struct rt_thread,
                              tlist);

    rt_current_thread = to_thread;

    /* switch to new thread,触发第一次任务调度 */
    rt_hw_context_switch_to((rt_uint32_t)&to_thread->sp);
#else
		register struct rt_thread *to_thread;
		register rt_ubase_t highest_ready_priority;
		/* 获取就绪的最高优先级*/
		highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1;
		/* 获取将要运行线程的线程控制块 */
    to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,
                              struct rt_thread,
                              tlist);
		rt_current_thread = to_thread;
		/* 切换到新的线程 */
		rt_hw_context_switch_to((rt_uint32_t)&to_thread->sp);
															
#endif
    /* never come back */
}

extern struct rt_thread idle;
extern struct rt_thread rt_flag1_thread;
extern struct rt_thread rt_flag2_thread;

/* 系统调度，非第一次调度 */
void rt_schedule(void)
{
		struct rt_thread *to_thread;
		struct rt_thread *from_thread;

#if 0
		/* 两个线程轮流切换 */
		if ( rt_current_thread == rt_list_entry( rt_thread_priority_table[0].next, struct rt_thread, tlist) )
		{
				from_thread = rt_current_thread;
				to_thread = rt_list_entry( rt_thread_priority_table[1].next, struct rt_thread, tlist);
				rt_current_thread = to_thread;
		}
		else
		{
				from_thread = rt_current_thread;
				to_thread = rt_list_entry( rt_thread_priority_table[0].next, struct rt_thread, tlist);
				rt_current_thread = to_thread;
		}
#elif 0
		/* 如果当前线程是空闲线程，那么就去尝试执行线程 1 或者线程 2，
		看看他们的延时时间是否结束，如果线程的延时时间均没有到期，那就返回继续执行空闲线程 */
		if ( rt_current_thread == &idle ) //当前线程为IDLE线程
		{
				if (rt_flag1_thread.remaining_tick == 0) //线程 rt_flag1_thread 就绪
				{
						//从哪里来，到哪里去
						from_thread = rt_current_thread;
						to_thread = &rt_flag1_thread;
						rt_current_thread = to_thread;
				}
				else if (rt_flag2_thread.remaining_tick == 0) //线程 rt_flag2_thread 就绪
				{
						from_thread = rt_current_thread;
						to_thread = &rt_flag2_thread;
						rt_current_thread = to_thread;
				}
				else
				{
						return;	/* 线程延时均没有到期则返回，继续执行空闲线程 */
				}
		}
		else	// 当前线程不为idle
		{
				/* 如果当前线程是线程 1 或者线程 2 的话，检查下另外一个线程,
				如果另外的线程不在延时中，就切换到该线程，否则，判断下当前线程是否应该进入延时状态，
				如果是的话，就切换到空闲线程，否则就不进行任何切换 */
			if (rt_current_thread == &rt_flag1_thread)//当前为线程1
				{
						if (rt_flag2_thread.remaining_tick == 0) //线程2阻塞到期，就绪，可以切到线程2
						{
								from_thread = rt_current_thread;
								to_thread = &rt_flag2_thread;
								rt_current_thread = to_thread;
						}
						else if (rt_current_thread->remaining_tick != 0) //线程2阻塞，当前线程即线程1还需要阻塞，切换到idle线程
						{
								from_thread = rt_current_thread;
								to_thread = &idle;
								rt_current_thread = to_thread;
						}
						else //线程2阻塞，线程1就绪
						{
								return; /* 返回，不进行切换，因为两个线程都处于延时中 */
						}
				}
				else if (rt_current_thread == &rt_flag2_thread)//当前为线程2
				{
						if (rt_flag1_thread.remaining_tick == 0) //线程1阻塞到期，就绪，可以切到线程1
						{
								from_thread = rt_current_thread;
								to_thread = &rt_flag1_thread;
								rt_current_thread = to_thread;
						}
						else if (rt_current_thread->remaining_tick != 0) //线程1阻塞，当前线程即线程2还需要阻塞，切换到idle线程
						{
								from_thread = rt_current_thread;
								to_thread = &idle;
								rt_current_thread = to_thread;
						}
						else //线程1阻塞，线程2就绪
						{
								return; /* 返回，不进行切换，因为两个线程都处于延时中 */
						}
				}
		}
#else
		rt_base_t level;
		register rt_ubase_t highest_ready_priority;
		/* 关中断 */
		level = rt_hw_interrupt_disable();
		/* 获取就绪的最高优先级 */
		highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1;
		/* 获取就绪的最高优先级对应的线程控制块 */
    to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,
                              struct rt_thread,
                              tlist);
		/* 如果目标线程不是当前线程，则要进行线程切换 */
		if (to_thread != rt_current_thread)
		{
				rt_current_priority = (rt_uint8_t)highest_ready_priority;
				from_thread = rt_current_thread;
				rt_current_thread = to_thread;
				rt_hw_context_switch((rt_uint32_t)&from_thread->sp, (rt_uint32_t)&to_thread->sp);
				/* 开中断 */
				rt_hw_interrupt_enable(level);
		}
															
		/* 开中断 */
		rt_hw_interrupt_enable(level);
#endif
		/* 产生上下文切换 */
//		rt_hw_context_switch((rt_uint32_t)&from_thread->sp,(rt_uint32_t)&to_thread->sp);
}

/* 调度器根据传入线程优先级向全局优先级表插入线程 */
void rt_schedule_insert_thread(struct rt_thread *thread)
{
		register rt_base_t temp;

		/* 关中断 */
		temp = rt_hw_interrupt_disable();

		/* 改变线程状态 */
		thread->stat = RT_THREAD_READY;

		/* 将线程插入就绪列表 */
		rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]), &(thread->tlist));

		/* 设置线程就绪优先级组中对应的位 */
		rt_thread_ready_priority_group |= thread->number_mask;

		/* 开中断 */
		rt_hw_interrupt_enable(temp);
}

/* 调度器根据传入线程优先级向全局优先级表删除线程 */
void rt_schedule_remove_thread(struct rt_thread *thread)
{
		register rt_base_t temp;
	
		/* 关中断 */
		temp = rt_hw_interrupt_disable();

		/* 将线程从就绪列表删除 */
		rt_list_remove(&(thread->tlist));
		/* 将线程就绪优先级组队员的位清除 */
		if (rt_list_isempty(&(rt_thread_priority_table[thread->current_priority])))
		{
				rt_thread_ready_priority_group &= ~thread->number_mask;//相应优先级组的bit清0
		}

		/* 开中断 */
		rt_hw_interrupt_enable(temp);
}

